﻿using System;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.ComponentModel;
using System.Drawing.Design;
using System.Reflection;
using System.IO;
using System.Data.Objects;
using UtfprLibrary.ComponentModel.Security;

namespace UtfprLibrary.Windows.Forms.ComponentModel {
    public class UtfprRestrictionEditor : UITypeEditor {
        #region Internal Properties

        internal ITypeDescriptorContext context;
        internal IWindowsFormsEditorService editorService;
        internal ObjectContext objectContext;

        #endregion

        #region Internal Methods

        /// <summary>
        /// Create a temp Domain with the UtfprSettings, using it to build an instance of ObjectContext
        /// and show the apropriate IWindowsFormsEditorService dialog.
        /// </summary>
        /// <returns>A Function, Operation or Module in the form of a IUtfprKeyName</returns>
        internal object createTemDomainAndObjectContextApplyingRestriction() {
            AppDomain appDomain = null;
            try {
                //pega por padrão a primeira connection string
                var connectionString = UtfprLibrary.Configurations.DesignTime.ConfigurationManager.ConnectionStrings[0];
                var assemblyName = UtfprLibrary.Configurations.DesignTime.UtfprSettings.Settings.Security.Type.AssemblyName;
                var typeName = UtfprLibrary.Configurations.DesignTime.UtfprSettings.Settings.Security.Type.TypeName;
                var path = UtfprLibrary.Configurations.DesignTime.UtfprSettings.Settings.ActiveProjectDebugPath;

                string assemblyPath = path + assemblyName;
                byte[] assemblyBuffer = File.ReadAllBytes(assemblyPath);

                appDomain = AppDomain.CreateDomain("TempDomain");
                var assembly = appDomain.Load(assemblyBuffer);

                this.objectContext = (ObjectContext)assembly.CreateInstance(
                    typeName, false, BindingFlags.CreateInstance, null,
                    new object[] { connectionString }, null, null);

                if (this.context.Instance.GetType().GetInterface(typeof(IUtfprModuleRestrictionService).FullName) != null) {
                    return moduleRestrictionService();
                } else if (this.context.Instance.GetType().GetInterface(typeof(IUtfprRestrictionService).FullName) != null) {
                    return restrictionService();
                }
            } catch (Exception ex) {
                throw ex;
            } finally {
                if (appDomain != null) {
                    AppDomain.Unload(appDomain);
                }
            }

            return null;
        }

        /// <summary>
        /// Shows a UtfprFormFunctionsRestrictionEditor (listing all Functions of the system, enabling the user to select a Function) 
        /// or a UtfprFormOperationsRestrictionEditor (listing Functions and Operations of the system, enabling the user to select a Operation) dialog, 
        /// depending if it is a Function or a Operation.
        /// </summary>
        /// <returns>A Function or Operation in the form of a IUtfprKeyName</returns>
        internal object restrictionService() {
            var restrictionService = this.context.Instance as IUtfprRestrictionService;
            if (restrictionService.IsFunctionRestriction) {
                var selectionControl = new UtfprFormFunctionsRestrictionEditor(objectContext);
                if (this.editorService.ShowDialog(selectionControl) == DialogResult.OK) {
                    return selectionControl.Value;
                }
            } else {
                var selectionControl = new UtfprFormOperationsRestrictionEditor(objectContext);
                if (this.editorService.ShowDialog(selectionControl) == DialogResult.OK) {
                    return selectionControl.Value;
                }
            }
            return null;
        }

        /// <summary>
        /// Shows a UtfprFormModulesRestrictionEditor dialog listing all Modules of the system, 
        /// enabling the user to select the Module of the System;
        /// </summary>
        /// <returns>A Module in the form of a IUtfprKeyName</returns>
        internal object moduleRestrictionService() {
            var moduleRestrictionService = this.context.Instance as IUtfprModuleRestrictionService;
            var selectionControl = new UtfprFormModulesRestrictionEditor(objectContext);
            if (this.editorService.ShowDialog(selectionControl) == DialogResult.OK) {
                return selectionControl.Value;
            }
            return null;
        }

        #endregion

        #region Override Methods

        /// <summary>
        /// Gets the editor style used by the EditValue method, and sets a internal variable
        /// </summary>
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
            this.context = context;
            return UITypeEditorEditStyle.Modal;
        }

        /// <summary>
        /// Indicates whether this editor supports painting a representation of an object's value.
        /// </summary>
        public override bool GetPaintValueSupported(ITypeDescriptorContext context) {
            return false;
        }

        /// <summary>
        /// Edits the specified object's value using the editor style indicated by the GetEditStyle method.
        /// </summary>
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {
            if (provider != null) {
                this.editorService = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
                if (editorService != null) {
                    value = createTemDomainAndObjectContextApplyingRestriction();
                }
            }
            return value;
        }

        #endregion
    }
}